﻿using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using System.Security.Claims;

namespace Single.AppCore
{
    public static class Authentication
    {
        private const string UserIdKey = "WORK-USERID";
        private const string NameKey = "WORK-NAME";
        private const string UserNameKey = "WORK-USERNAME";
        private const string AvatarKey = "WORK-AVATAR";
        private const string IsSuperKey = "WORK-ISSUPER";

        /// <summary>
        /// 验证请求类型
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        private static bool IsAjaxRequest(HttpRequest request)
        {
            return string.Equals(request.Query["X-Requested-With"], "XMLHttpRequest", StringComparison.Ordinal)
                || string.Equals(request.Headers["X-Requested-With"], "XMLHttpRequest", StringComparison.Ordinal);
        }

        /// <summary>
        /// 此函数太过厉害暂时没有名称
        /// </summary>
        /// <param name="services"></param>
        /// <param name="scheme"></param>
        /// <param name="url"></param>
        /// <param name="formRedirect">设置表单提交类型是否页面跳转</param>
        /// <returns></returns>
        public static AuthenticationBuilder AddAuthentication(this IServiceCollection services, string scheme, string url, bool formRedirect, string timeoutJson)
        {
            // 设置默认方案名称
            return services.AddAuthentication(opts => { opts.DefaultScheme = scheme; }).AddCookie(scheme, opts =>
            {
                // 超时时间
                opts.ExpireTimeSpan = TimeSpan.FromDays(1);
                // 滑动到期
                opts.SlidingExpiration = true;

                // 重写跳转到登录页事件
                opts.Events.OnRedirectToLogin = context =>
                {
                    if (IsAjaxRequest(context.Request) || (!formRedirect && context.Request.HasFormContentType))
                    {
                        context.Response.Clear();
                        context.Response.StatusCode = 400;
                        return context.Response.WriteAsync(timeoutJson);
                    }
                    // 非 Ajax 请求情况下正常跳转登录页面
                    context.Response.Redirect(url); return Task.CompletedTask;
                };
            });
        }

        /// <summary>
        /// 执行登录
        /// </summary>
        /// <param name="context"></param>
        /// <param name="scheme"></param>
        /// <param name="userid"></param>
        /// <param name="username"></param>
        public static async Task<Task> SignInAsync(this HttpContext context, string scheme, long userid, string name, string username, string avatar, bool isSuper)
        {
            var claims = new List<Claim> {
                new Claim(UserIdKey, userid.ToString()),
                new Claim(NameKey, name),
                new Claim(UserNameKey, username),
                new Claim(AvatarKey, avatar ?? string.Empty),
                new Claim(IsSuperKey, isSuper.ToString())
            };
            var claimsIdentity = new ClaimsIdentity(claims, scheme);
            var claimsPrincipal = new ClaimsPrincipal(claimsIdentity);

            await context.SignInAsync(scheme, claimsPrincipal, new AuthenticationProperties()
            {
                AllowRefresh = true,
                IsPersistent = true
            });

            return Task.CompletedTask;
        }

        /// <summary>
        /// 用户编号
        /// </summary>
        /// <param name="claimsPrincipal"></param>
        /// <returns></returns>
        public static long GetUserId(this ClaimsPrincipal claimsPrincipal)
        {
            var value = claimsPrincipal.FindFirst(UserIdKey)?.Value;

            return long.TryParse(value, out var userId) ? userId : 0;
        }

        /// <summary>
        /// 用户姓名
        /// </summary>
        /// <param name="claimsPrincipal"></param>
        /// <returns></returns>
        public static string GetName(this ClaimsPrincipal claimsPrincipal)
        {
            return claimsPrincipal.FindFirst(NameKey)?.Value;
        }

        /// <summary>
        /// 用户账号
        /// </summary>
        /// <param name="claimsPrincipal"></param>
        /// <returns></returns>
        public static string GetUserName(this ClaimsPrincipal claimsPrincipal)
        {
            return claimsPrincipal.FindFirst(UserNameKey)?.Value;
        }

        /// <summary>
        /// 用户头像
        /// </summary>
        /// <param name="claimsPrincipal"></param>
        /// <returns></returns>
        public static string GetAvatar(this ClaimsPrincipal claimsPrincipal)
        {
            return claimsPrincipal.FindFirst(AvatarKey)?.Value;
        }

        /// <summary>
        /// 是否超级管理员
        /// </summary>
        /// <param name="claimsPrincipal"></param>
        /// <returns></returns>
        public static bool GetIsSuper(this ClaimsPrincipal claimsPrincipal)
        {
            bool isSuper = false;

            bool.TryParse(claimsPrincipal.FindFirst(IsSuperKey)?.Value, out isSuper);

            return isSuper;
        }
    }
}